package com.smec.moblie.crash;

import android.annotation.SuppressLint;
import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Build;
import android.os.Environment;
import android.os.Looper;
import android.telephony.TelephonyManager;
import android.util.Log;

import com.smec.moblie.activity.LoginActivity;

import org.litepal.crud.DataSupport;

import java.io.DataInputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.Thread.UncaughtExceptionHandler;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.TimeZone;

/**
 * 网络环境正常的时候直接上传，如果不正常保存到本地数据库里面， 下次启动的时候检查数据库里面是否有数据若有数据并且此时网络正常上传并删掉上传成功的数据。
 *
 * @author xinwei.sun
 */
@SuppressLint("NewApi")
public class CustomCrashHandler implements UncaughtExceptionHandler {
    private static final String TAG = "Activity";
    private Context mContext;
    private static final String SDCARD_ROOT = Environment.getExternalStorageDirectory().toString();
    private static CustomCrashHandler mInstance = new CustomCrashHandler();
    public static String CRASHUPLOADPATH = "http://bpmpublic.smec-cn.com:8011/Fnd_Service/FndAppCrashLogService/appCrashLogServicePS";

    private CustomCrashHandler() {

    }

    /**
     * 单例模式，保证只有一个CustomCrashHandler实例存在
     *
     * @return
     */
    public static CustomCrashHandler getInstance() {
        return mInstance;
    }

    /**
     * 异常发生时，系统回调的函数，我们在这里处理一些操作
     */
    @Override
    public void uncaughtException(Thread thread, Throwable ex) {
        try {
            showToast(mContext, "程序出错即将退出，错误信息已发送至相关部门进行处理。");
            thread.sleep(4800);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        if (checkNet(mContext)) {
            sendCrashLog(savaCrash(mContext, ex, false));
        } else {
            savaCrash(mContext, ex, true);
        }

    }

    /**
     * 为我们的应用程序设置自定义Crash处理
     */
    public void setCustomCrashHanler(Context context) {
        mContext = context;
        Thread.setDefaultUncaughtExceptionHandler(this);
        getData();
    }

    /**
     * 显示提示信息，需要在线程中显示Toast
     *
     * @param context
     * @param msg
     */
    private void showToast(final Context context, final String msg) {
        new Thread(new Runnable() {

            @Override
            public void run() {
                Looper.prepare();
                AndroidUtil.toast(context, msg, 5);
                Looper.loop();
            }
        }).start();
    }

    /**
     * 获取系统未捕捉的错误信息
     *
     * @param throwable
     * @return
     */
    private String obtainExceptionInfo(Throwable throwable) {
        StringWriter mStringWriter = new StringWriter();
        PrintWriter mPrintWriter = new PrintWriter(mStringWriter);
        throwable.printStackTrace(mPrintWriter);
        mPrintWriter.close();
        Log.e(TAG, mStringWriter.toString());
        return mStringWriter.toString();
    }

    /**
     * 保存获取的 软件信息，设备信息和出错信息保存在sqlite中
     *
     * @param context
     * @param ex
     * @return
     */
    private CrashBean savaCrash(Context context, Throwable ex, boolean isSave) {
        TelephonyManager tm = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
        String deviceid = tm.getDeviceId();
        String nameString = context.getSharedPreferences("ElevatorSharedPreferences", LoginActivity.MODE_PRIVATE).getString("USERNAME", "");
//		if ("20000458".equals(nameString)) {
//			nameString = "f300018";
//		}
        CrashBean crashBean = new CrashBean();
        crashBean.setUser(nameString);
        crashBean.setAppVersion(AndroidUtil.getAppVersionName(context) + "");
        crashBean.setAppName("新版维保");
        crashBean.setImei(deviceid);
        crashBean.setModel(Build.MODEL);
        crashBean.setCrashLog(obtainExceptionInfo(ex));
        crashBean.setCrashTime(paserTime(System.currentTimeMillis()));
        if (isSave) {
            crashBean.save();
            ExitAppUtils.getInstance().exit();
        }
        return crashBean;
    }

    /**
     * 将毫秒数转换成yyyy-MM-dd-HH-mm-ss的格式
     *
     * @param milliseconds
     * @return
     */
    private String paserTime(long milliseconds) {
        System.setProperty("user.timezone", "Asia/Shanghai");
        TimeZone tz = TimeZone.getTimeZone("Asia/Shanghai");
        TimeZone.setDefault(tz);
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");
        String times = format.format(new Date(milliseconds));
        return times;
    }

    private void sendCrashLog(final CrashBean crashBean) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    getResultForHttpGet(AndroidUtil.upStrnull(crashBean.getUser()), AndroidUtil.upStrnull(crashBean.getImei()), AndroidUtil.upStrnull(crashBean.getAppName()),
                            AndroidUtil.upStrnull(crashBean.getAppVersion()), AndroidUtil.upStrnull(crashBean.getModel()), AndroidUtil.upStrnull(crashBean.getCrashLog()),
                            AndroidUtil.upStrnull(crashBean.getCrashTime()), "java");
                    ExitAppUtils.getInstance().exit();
                } catch (Exception e) {
                    crashBean.save();
                }
            }
        }).start();
    }

    /**
     * @param appUser       用户名
     * @param imei          设备串号
     * @param appName       app平台名称
     * @param appVersion    版本号
     * @param deviceVersion 机器型号
     * @param crashLog      错误日志
     * @param crashTime     报错时间
     * @param crashType     crash类型
     * @return
     */
    public String getResultForHttpGet(String appUser, String imei, String appName, String appVersion, String deviceVersion, String crashLog, String crashTime, String crashType) throws Exception {

        String uri = CRASHUPLOADPATH + "?appUser=" + URLEncoder.encode(appUser, "UTF-8") + "&imei=" + URLEncoder.encode(imei, "UTF-8") + "&appName=" + URLEncoder.encode(appName, "UTF-8")
                + "&appVersion=" + appVersion + "&deviceVersion=" + URLEncoder.encode(deviceVersion, "UTF-8") + "&crashLog=" + URLEncoder.encode(crashLog, "UTF-8") + "&crashTime="
                + URLEncoder.encode(crashTime, "UTF-8") + "&crashType=" + crashType;
        String result = "";
        URL url = new URL(uri);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setConnectTimeout(30000);
        conn.setRequestMethod("GET");
        conn.connect();
        DataInputStream dis = new DataInputStream(conn.getInputStream());
        result = dis.readLine();
        if (conn.getResponseCode() != HttpURLConnection.HTTP_OK) {
            return "";
        }
        return result;
    }

    /**
     * 获取本地crash日志 若不为空上传并删除
     */
    private void getData() {
        ArrayList<CrashBean> crashList = new ArrayList<>();
        crashList = (ArrayList<CrashBean>) DataSupport.findAll(CrashBean.class);
        if (null != crashList) {
            final CrashBean crashBean;
            if (crashList.isEmpty()) {

            } else {
                crashBean = crashList.get(0);
                try {
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            try {
                                String result = getResultForHttpGet(AndroidUtil.upStrnull(crashBean.getUser()), AndroidUtil.upStrnull(crashBean.getImei()),
                                        AndroidUtil.upStrnull(crashBean.getAppName()), AndroidUtil.upStrnull(crashBean.getAppVersion()), AndroidUtil.upStrnull(crashBean.getModel()),
                                        AndroidUtil.upStrnull(crashBean.getCrashLog()), AndroidUtil.upStrnull(crashBean.getCrashTime()), "java");
                                if (result.contains("success")) {
                                    DataSupport.deleteAll(CrashBean.class);
                                }
                            } catch (Exception e) {

                            }
                        }
                    }).start();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }


    /**
     * 检查网络
     *
     * @param context
     * @return
     */
    public static boolean checkNet(Context context) {
        // 获得手机所有连接管理对象（包括对wi-fi等连接的管理）
        try {
            ConnectivityManager connectivity = (ConnectivityManager) context
                    .getSystemService(Context.CONNECTIVITY_SERVICE);
            if (connectivity != null) {
                // 获得网络连接管理的对象
                NetworkInfo info = connectivity.getActiveNetworkInfo();
                if (info != null && info.isConnected()) {
                    // 判断当前网络是否已连接
                    if (info.getState() == NetworkInfo.State.CONNECTED) {
                        return true;
                    }
                }
            }
        } catch (Exception e) {
        }
        return false;
    }
}
